package com.zbkj.crmeb.marketing.service.impl;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.utils.CrmebUtil;
import com.zbkj.crmeb.enums.WeekEnum;
import com.zbkj.crmeb.store.model.StoreCouponUserPhone;
import com.zbkj.crmeb.store.service.StoreCouponUserPhoneService;
import com.zbkj.crmeb.user.model.UserMemberRecord;
import com.zbkj.crmeb.user.request.UserSearchRequest;
import com.zbkj.crmeb.user.response.UserResponse;
import com.zbkj.crmeb.user.service.UserMemberRecordService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.PageParamRequest;
import com.crmeb.core.exception.CrmebException;
import com.github.pagehelper.PageHelper;
import com.zbkj.crmeb.enums.CouponUseTypeEnum;
import com.zbkj.crmeb.enums.CouponUserTypeEnum;
import com.zbkj.crmeb.marketing.dao.StoreCouponDao;
import com.zbkj.crmeb.marketing.model.StoreCoupon;
import com.zbkj.crmeb.marketing.model.StoreCouponUser;
import com.zbkj.crmeb.marketing.request.StoreCouponRequest;
import com.zbkj.crmeb.marketing.request.StoreCouponSearchRequest;
import com.zbkj.crmeb.marketing.response.StoreCouponInfoResponse;
import com.zbkj.crmeb.marketing.service.StoreCouponService;
import com.zbkj.crmeb.marketing.service.StoreCouponUserService;
import com.zbkj.crmeb.merchant.admin.service.MerStoreProductService;
import com.zbkj.crmeb.store.model.StoreOrder;
import com.zbkj.crmeb.store.model.StoreProductCoupon;
import com.zbkj.crmeb.store.response.StoreProductResponse;
import com.zbkj.crmeb.store.service.StoreOrderService;
import com.zbkj.crmeb.store.service.StoreProductCouponService;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.service.UserService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class StoreCouponServiceImpl extends ServiceImpl<StoreCouponDao, StoreCoupon> implements StoreCouponService {
	@Autowired
	private StoreCouponDao storeCouponDao;
	@Autowired
	private UserService userService;
	@Autowired
	private StoreOrderService storeOrderService;
	@Autowired
	private StoreCouponUserService storeCouponUserService;
	@Autowired
	private StoreProductCouponService storeProductCouponService;
	@Autowired
	private MerStoreProductService merStoreProductService;
	@Autowired
	private UserMemberRecordService userMemberRecordService;
	@Autowired
	private StoreCouponUserPhoneService storeCouponUserPhoneService;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveEntity(StoreCouponRequest request) {
		StoreCoupon storeCoupon = new StoreCoupon();
		BeanUtils.copyProperties(request, storeCoupon);
		storeCoupon.setLastTotal(storeCoupon.getTotal());
		storeCoupon.setReadTotal(0);
		if (null != request.getPrimaryKey()) {
			storeCoupon.setPrimaryKey(request.getPrimaryKey().toJSONString());
		}
		storeCoupon.setCreateTime(new Date());
		storeCoupon.setUpdateTime(new Date());

		boolean b = save(storeCoupon);

		// 指定手机号用户
		if (request.getCrowd() == 6) {
			// 指定的手机号列表
			List<String> phones = CrmebUtil.stringToArrayStr(request.getPhones());
			QueryWrapper<User> queryWrapper = new QueryWrapper<>();
			queryWrapper.in("SUBSTR(phone ,5)", phones);
			queryWrapper.lambda().eq(User::getMerId, request.getMerId());
			List<User> users = userService.list(queryWrapper);
			List<StoreCouponUserPhone> storeCouponUserPhones = new ArrayList<>();
			// 没有符合要求的用户，所有用户添加失败记录
			if (CollectionUtils.isEmpty(users)) {
				phones.forEach(phone -> {
					StoreCouponUserPhone storeCouponUserPhone = new StoreCouponUserPhone();
					storeCouponUserPhone.setCouponId(storeCoupon.getId());
					storeCouponUserPhone.setPhone(phone);
					storeCouponUserPhone.setStatus(false);
					storeCouponUserPhones.add(storeCouponUserPhone);
				});
			} else {
				// 存在的手机号
				List<String> existPhone = users.stream().map(User::getPhone).map(phone -> phone.substring(4)).collect(Collectors.toList());
				// 清除存在的手机号
				phones.removeAll(existPhone);
				existPhone.forEach(phone -> {
					StoreCouponUserPhone storeCouponUserPhone = new StoreCouponUserPhone();
					storeCouponUserPhone.setCouponId(storeCoupon.getId());
					storeCouponUserPhone.setPhone(phone);
					storeCouponUserPhone.setStatus(true);
					storeCouponUserPhones.add(storeCouponUserPhone);
				});
				phones.forEach(phone -> {
					StoreCouponUserPhone storeCouponUserPhone = new StoreCouponUserPhone();
					storeCouponUserPhone.setCouponId(storeCoupon.getId());
					storeCouponUserPhone.setPhone(phone);
					storeCouponUserPhone.setStatus(false);
					storeCouponUserPhones.add(storeCouponUserPhone);
				});
			}
			storeCouponUserPhoneService.saveBatch(storeCouponUserPhones);
		}

		// 指定商品
		if (b && request.getUseType() == CouponUseTypeEnum.GOODS.getCode()) {
			List<Integer> goodsIds = request.getGoodsIds();
			List<StoreProductCoupon> storeProductCoupons = new ArrayList<>();
			goodsIds.stream().forEach(obj -> {
				StoreProductCoupon storeProductCoupon = new StoreProductCoupon();
				storeProductCoupon.setIssueCouponId(storeCoupon.getId());
				storeProductCoupon.setProductId(obj);
				storeProductCoupons.add(storeProductCoupon);
			});

			storeProductCouponService.saveBatch(storeProductCoupons);
		}

		return b;
	}

	@Override
	public List<StoreCoupon> pageEntity(StoreCouponSearchRequest request, PageParamRequest pageParamRequest) {
		PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());

		LambdaQueryWrapper<StoreCoupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(StoreCoupon::getIsDel, false);
		lambdaQueryWrapper.eq(StoreCoupon::getMerId, request.getMerId());
		lambdaQueryWrapper.eq(StoreCoupon::getIsPartition, false);

		if (null != request.getName()) {
			lambdaQueryWrapper.like(StoreCoupon::getName, request.getName());
		}
		if (null != request.getUseType()) {
			lambdaQueryWrapper.eq(StoreCoupon::getUseType, request.getUseType());
		}
		if (null != request.getTag()) {
			lambdaQueryWrapper.like(StoreCoupon::getTag, request.getTag());
		}
		if (null != request.getStartTime()) {
			lambdaQueryWrapper.gt(StoreCoupon::getCreateTime, request.getStartTime());
		}
		if (null != request.getEndTime()) {
			lambdaQueryWrapper.lt(StoreCoupon::getCreateTime, request.getEndTime());
		}
		if (Objects.nonNull(request.getCrowd())) {
			lambdaQueryWrapper.eq(StoreCoupon::getCrowd, request.getCrowd());
		}
		lambdaQueryWrapper.orderByDesc(StoreCoupon :: getCreateTime);

		return storeCouponDao.selectList(lambdaQueryWrapper);
	}

	@Override
	public List<StoreCoupon> listEntity(StoreCouponSearchRequest request) {
		LambdaQueryWrapper<StoreCoupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(StoreCoupon::getIsDel, false);
		lambdaQueryWrapper.eq(null != request.getMerId(), StoreCoupon::getMerId, request.getMerId());

		if (null != request.getName()) {
			lambdaQueryWrapper.like(StoreCoupon::getName, request.getName());
		}
		if (null != request.getUseType()) {
			lambdaQueryWrapper.eq(StoreCoupon::getUseType, request.getUseType());
		}
		if (null != request.getStatus()) {
			lambdaQueryWrapper.eq(StoreCoupon::getStatus, request.getStatus());
		}
		if (null != request.getType()) {
			lambdaQueryWrapper.eq(StoreCoupon::getType, request.getType());
		}
		if (null != request.getIsReceiveOver() && request.getIsReceiveOver()) {
			//时间过滤时需要查询按月发放的数据
			lambdaQueryWrapper.lt(StoreCoupon::getReceiveStartTime, new Date());
			lambdaQueryWrapper.and(i -> i.isNull(StoreCoupon::getReceiveEndTime).or().gt(StoreCoupon::getReceiveEndTime, new Date()));
			/*lambdaQueryWrapper.lt(StoreCoupon::getReceiveStartTime, new Date());
			lambdaQueryWrapper.gt(StoreCoupon::getReceiveEndTime, new Date());*/
		}
		if (null != request.getIsUseOver() && request.getIsUseOver()) {
			lambdaQueryWrapper.and(qw -> qw.eq(StoreCoupon::getIsFixedTime, false).or(qwq -> qwq
					.lt(StoreCoupon::getUseStartTime, new Date()).gt(StoreCoupon::getUseEndTime, new Date())));
		}
		if (null != request.getTag()) {
			lambdaQueryWrapper.like(StoreCoupon::getTag, request.getTag());
		}
		if (null != request.getStartTime()) {
			lambdaQueryWrapper.gt(StoreCoupon::getCreateTime, request.getStartTime());
		}
		if (null != request.getEndTime()) {
			lambdaQueryWrapper.lt(StoreCoupon::getCreateTime, request.getEndTime());
		}
		if (Objects.nonNull(request.getCrowd())) {
			lambdaQueryWrapper.eq(StoreCoupon::getCrowd, request.getCrowd());
		}
		if (BooleanUtil.isTrue(request.getFilterMemberFlag())){
			lambdaQueryWrapper.ne(StoreCoupon::getCrowd,4);
		}
		lambdaQueryWrapper.orderByDesc(StoreCoupon::getCreateTime);

		return storeCouponDao.selectList(lambdaQueryWrapper);
	}

	@Override
	public StoreCouponInfoResponse info(Integer id) {
		try {
			StoreCoupon storeCoupon = getById(id);
			if (storeCoupon == null || storeCoupon.getIsDel()) {
				throw new CrmebException("优惠券信息不存在或者已失效！");
			}

			StoreCouponInfoResponse coupon = new StoreCouponInfoResponse();
			BeanUtils.copyProperties(storeCoupon, coupon);

			// 指定商品券
			if (coupon.getUseType() == CouponUseTypeEnum.GOODS.getCode()) {
				List<StoreProductCoupon> storeProductCoupons = storeProductCouponService
						.list(Wrappers.<StoreProductCoupon>lambdaQuery().eq(StoreProductCoupon::getIssueCouponId, id));
				List<Integer> productIds = storeProductCoupons.stream().map(obj -> obj.getProductId()).collect(Collectors.toList());
				List<StoreProductResponse> storeProductResponses = merStoreProductService.getMerchnatList(productIds, storeCoupon.getMerId(),false);

				coupon.setProductIds(productIds);
				coupon.setProducts(storeProductResponses);
			}

			return coupon;
		} catch (Exception e) {
			throw new CrmebException(e.getMessage());
		}
	}

	/**
	 * 优惠券领取
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
	public Boolean bindCouponByUser(List<Integer> userIds, Integer couponId, CouponUserTypeEnum type) {
		if (CollectionUtils.isEmpty(userIds) || null == couponId || null == type) {
			throw new CrmebException("参数异常!");
		}

		// 优惠券领取相关逻辑
		String lock = getLock(couponId.toString());
		synchronized (lock) {
			List<StoreCouponUser> storeCouponUserSaves = new ArrayList<>();
			StoreCoupon storeCoupon = null;

			for (Integer userId : userIds) {
				User user = userService.getById(userId);
				if (null == user) {
					throw new CrmebException("用户不存在！");
				}

				long nowTime = Timestamp.valueOf(LocalDateTime.now()).getTime();

				storeCoupon = storeCouponDao.selectById(couponId);
				List<StoreCouponUser> storeCouponUsers = storeCouponUserService
						.list(Wrappers.<StoreCouponUser>lambdaQuery().eq(StoreCouponUser::getUid, userId)
								.eq(StoreCouponUser::getCouponId, couponId));
				if (null == storeCoupon) {
					log.info("--------------- 用户id: {}, 优惠券id: {}, 优惠券不存在! ---------------", userId, couponId);
					throw new CrmebException("优惠券不存在!");
				}
				if (null == type) {
					log.info("--------------- 用户id: {}, 优惠券id: {}, 优惠券类型不存在! ---------------", userId, couponId);
					throw new CrmebException("优惠券类型不存在!");
				}
				if (storeCoupon.getStatus()) {
					log.info("--------------- 用户id: {}, 优惠券id: {}, 优惠券开启后关闭! ---------------", userId, couponId);
					throw new CrmebException("优惠券已失效, 领取失败!");
				}
				if (storeCoupon.getMerId().intValue() != user.getMerId().intValue()) {
					log.info("--------------- 用户id: {}, 优惠券id: {}, 优惠券状态不符! ---------------", userId, couponId);
					throw new CrmebException("优惠券状态不符!");
				}
				if (userIds.size() > storeCoupon.getLastTotal()) {
					log.info("--------------- 用户id: {}, 优惠券id: {}, 发放数量已领取完! ---------------", userId, couponId);
					throw new CrmebException("优惠券发放数量已领完，领取失败!");
				}
				if (storeCoupon.getReleaseType() == 1 && nowTime > storeCoupon.getReceiveEndTime().getTime()) {
					log.info("--------------- 用户id: {}, 优惠券id: {}, 领取时间已过期的优惠券! ---------------", userId, couponId);
					throw new CrmebException("优惠券领取时间已过期，领取失败!");
				}
				if (storeCoupon.getReleaseType() == 1 && nowTime < storeCoupon.getReceiveStartTime().getTime()) {
					log.info("--------------- 用户id: {}, 优惠券id: {}, 优惠券可领取时间还未开始! ---------------", userId, couponId);
					throw new CrmebException("优惠券领取时间未开始，领取失败!");
				}
				if (0 != storeCoupon.getLimitTotal() && storeCouponUsers.size() >= storeCoupon.getLimitTotal()) {
					log.info("--------------- 用户id: {}, 优惠券id: {}, 用户领取数量超额! ---------------", userId, couponId);
					throw new CrmebException("优惠券领取数量已超额，领取失败!");
				}
				// 无订单用户
				if (2 == storeCoupon.getCrowd()) {
					int orderCount = storeOrderService
							.count(Wrappers.<StoreOrder>lambdaQuery().eq(StoreOrder::getUid, userId));
					if (0 < orderCount) {
						log.info("--------------- 用户id: {}, 优惠券id: {}, 指定的用户领取失败! ---------------", userId, couponId);
						throw new CrmebException("该优惠券仅部分用户可领取，领取失败!");
					}
				}
				// 新用户
				if (3 == storeCoupon.getCrowd()) {
					if (user.getCreateTime().getTime() < storeCoupon.getCreateTime().getTime()) {
						log.info("--------------- 用户id: {}, 优惠券id: {}, 指定的用户领取失败! ---------------", userId, couponId);
						throw new CrmebException("该优惠券仅部分用户可领取，领取失败!");
					}
				}
				// 会员用户
				if (4 == storeCoupon.getCrowd()) {
					//查询用户是否已开启会员
					List<UserMemberRecord> userMemberRecordList = userMemberRecordService.list(Wrappers.lambdaQuery(UserMemberRecord.class)
							.eq(UserMemberRecord::getPaid,true)
							.gt(UserMemberRecord::getExpirationTime,new Date())
							.eq(UserMemberRecord::getUid,user.getUid()));
					if (CollectionUtils.isEmpty(userMemberRecordList)){
						throw new CrmebException("该优惠券仅会员用户可领取，领取失败!");
					}
				}
				// 自定义人群
				if (5 == storeCoupon.getCrowd()) {
					// 查询用户分群下有哪些用户
					QueryWrapper<User> queryWrapper = new QueryWrapper<>();
					queryWrapper.apply(CrmebUtil.getFindInSetSql("feature_id", storeCoupon.getFeatureId()));
					queryWrapper.groupBy("uid");
					queryWrapper.lambda().eq(User::getMerId, storeCoupon.getMerId());
					List<User> userList = userService.list(queryWrapper);
					if (CollectionUtils.isEmpty(userList)) {
						throw new CrmebException("该优惠券仅部分用户可领取，领取失败!");
					}
					List<Integer> uids = userList.stream().map(User::getUid).collect(Collectors.toList());
					// 用户分群中没有该用户
					if (!uids.contains(userId)) {
						throw new CrmebException("该优惠券仅部分用户可领取，领取失败!");
					}
				}
				// 指定手机号
				if (6 == storeCoupon.getCrowd()) {
					List<StoreCouponUserPhone> storeCouponUserPhones = storeCouponUserPhoneService.list(Wrappers.<StoreCouponUserPhone>lambdaQuery().eq(StoreCouponUserPhone::getCouponId, storeCoupon.getId()).eq(StoreCouponUserPhone::getStatus, true));
					if (CollectionUtils.isEmpty(storeCouponUserPhones)) {
						throw new CrmebException("该优惠券仅部分用户可领取，领取失败!");
					}
					List<String> phones = storeCouponUserPhones.stream().map(StoreCouponUserPhone::getPhone).collect(Collectors.toList());
					if (!phones.contains(user.getPhone().substring(4))) {
						throw new CrmebException("该优惠券仅部分用户可领取，领取失败!");
					}
				}

				StoreCouponUser storeCouponUser = new StoreCouponUser();
				BeanUtils.copyProperties(storeCoupon, storeCouponUser);
				storeCouponUser.setCouponId(storeCoupon.getId());
				storeCouponUser.setUid(userId);
				storeCouponUser.setUserNick(user.getNickname());
				storeCouponUser.setUserPhone(user.getPhone());
				storeCouponUser.setType(type.getCode());
				// 固定时间
				if (storeCoupon.getIsFixedTime()) {
					storeCouponUser.setStartTime(storeCoupon.getUseStartTime());
					storeCouponUser.setEndTime(storeCoupon.getUseEndTime());
					// 有效天数
				} else {
					LocalDateTime time = LocalDateTime.now();
					LocalDateTime startTime = time.plusDays(storeCoupon.getLastDay());
					LocalDateTime endTime = startTime.plusDays(storeCoupon.getDay());

					ZoneId zoneId = ZoneId.systemDefault();
					Date startDate = Date.from(startTime.atZone(zoneId).toInstant());
					Date endDate = Date.from(endTime.atZone(zoneId).toInstant());

					storeCouponUser.setStartTime(startDate);
					storeCouponUser.setEndTime(endDate);
				}

				storeCouponUser.setCreateTime(new Date());
				storeCouponUser.setUpdateTime(new Date());
				storeCouponUserSaves.add(storeCouponUser);
			}

			// 优惠券扣减
			int updateCount = storeCouponDao.updateCouponTotal(couponId, userIds.size());
			if (0 >= updateCount) {
				throw new CrmebException("优惠券发放数量已领完，领取失败!");
			}
			boolean updateUser = storeCouponUserService.saveBatch(storeCouponUserSaves);
			if (!updateUser) {
				throw new CrmebException("发放异常!");
			}

			return true;
		}
	}

	@Override
	public void bindCouponByRegisterUser(Integer userId) {
		log.info("--------------- 新用户: {}注册自动发放优惠券 ---------------", userId);

		User user = userService.getById(userId);
		if (null == user) {
			log.info("--------------- 新用户: {}注册自动发放优惠券, 用户不存在 ---------------", userId);
			return;
		}
		// 查询可发放优惠券
		List<StoreCoupon> storeCoupons = this.list(Wrappers.<StoreCoupon>lambdaQuery().eq(StoreCoupon::getIsDel, false)
				.eq(StoreCoupon::getMerId, user.getMerId()).eq(StoreCoupon::getCrowd, 3)
				.eq(StoreCoupon::getStatus, false).gt(StoreCoupon::getLastTotal, 0)
				.lt(StoreCoupon::getReceiveStartTime, new Date()).gt(StoreCoupon::getReceiveEndTime, new Date())
				.lt(StoreCoupon::getCreateTime, user.getCreateTime()));
		log.info("--------------- 新用户: {}注册自动发放优惠券, 可发放优惠券列表 ---------------", JSON.toJSONString(storeCoupons));

		// 优惠券自动发放
		for (StoreCoupon storeCoupon : storeCoupons) {
			try {
				this.bindCouponByUser(Collections.singletonList(userId), storeCoupon.getId(), CouponUserTypeEnum.AUTO);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public Boolean checkCoupon(Integer couponUserId) {
		String lock = getLock(couponUserId.toString());

		synchronized (lock) {
			long nowTime = Timestamp.valueOf(LocalDateTime.now()).getTime();
			StoreCouponUser storeCouponUser = storeCouponUserService.getById(couponUserId);
			if (null == storeCouponUser) {
				throw new CrmebException("优惠券不存在!");
			}
			if (0 != storeCouponUser.getStatus()) {
				log.info("--------------- 优惠券已失效或已使用 ---------------");
				return false;
			}
			if (nowTime < storeCouponUser.getStartTime().getTime()
					|| nowTime > storeCouponUser.getEndTime().getTime()) {
				log.info("--------------- 优惠券不在可使用时间内 ---------------");
				return false;
			}
		}

		return true;
	}

	/**
	 * 功能描述: 获取指定手机号类型的手机号详情
	 * @Param: [id, status]
	 * @Return: java.util.List<com.zbkj.crmeb.store.model.StoreCouponUserPhone>
	 * @Author: wangzh
	 * @Date: 2023/3/27 11:04
	 */
	@Override
	public List<StoreCouponUserPhone> getPhoneInfos(Integer id, Boolean status) {
		StoreCoupon storeCoupon = this.getById(id);
		if (!Objects.equals(storeCoupon.getCrowd(), 6)) {
			throw new CrmebException("优惠券类型不为指定手机号客户，不能查询手机号！");
		}
		return storeCouponUserPhoneService.list(Wrappers.<StoreCouponUserPhone>lambdaQuery()
				.eq(StoreCouponUserPhone::getCouponId, id)
				.eq(StoreCouponUserPhone::getStatus, status));
	}

	/**
	 * 功能描述: 自动发放优惠券
	 * @Param: []
	 * @Return: void
	 * @Author: wangzh
	 * @Date: 2023/3/28 15:19
	 */
	@Override
	public void bindCouponBySystem() {
		Integer lock = 0;
		synchronized (lock) {
			List<Integer> crowds = Arrays.asList(1, 2, 5, 6);
			for (Integer crowd : crowds) {
				// 按月/周发放优惠券列表
				List<StoreCoupon> storeCoupons = getListByCrowd(crowd);
				// 该类型没有需要发放的优惠券
				if (CollectionUtils.isEmpty(storeCoupons)) {
					continue;
				}
				// 所有发放优惠券的商户
				List<Integer> merIds = storeCoupons.stream().map(StoreCoupon::getMerId).distinct().collect(Collectors.toList());

				// 查看当月/周是否有用户已领取优惠券，避免多次发放
				Map<Integer, List<StoreCoupon>> couponMap = storeCoupons.stream().collect(Collectors.groupingBy(StoreCoupon::getReleaseType));
				List<StoreCoupon> month = couponMap.get(2);
				List<StoreCoupon> week = couponMap.get(3);
				List<StoreCouponUser> receivedList = new ArrayList<>();
				if (CollectionUtils.isNotEmpty(month)) {
					List<Integer> ids = month.stream().map(StoreCoupon::getId).collect(Collectors.toList());
					List<StoreCouponUser> list = storeCouponUserService.list(Wrappers.<StoreCouponUser>lambdaQuery()
							.in(StoreCouponUser::getCouponId, ids)
							.apply("DATE_FORMAT( create_time, '%Y%m' ) = DATE_FORMAT( now(), '%Y%m' ) "));
					receivedList.addAll(list);
				}
				if (CollectionUtils.isNotEmpty(week)) {
					List<Integer> ids = week.stream().map(StoreCoupon::getId).collect(Collectors.toList());
					List<StoreCouponUser> list = storeCouponUserService.list(Wrappers.<StoreCouponUser>lambdaQuery()
							.in(StoreCouponUser::getCouponId, ids)
							.ge(StoreCouponUser::getCreateTime, LocalDate.now().minusDays(7))
							.le(StoreCouponUser::getCreateTime, LocalDateTime.now()));
					receivedList.addAll(list);
				}
				List<User> users = new ArrayList<>();
				// 所有用户
				if (crowd == 1) {
					users = userService.list(Wrappers.<User>lambdaQuery().in(User::getMerId, merIds));
				// 无订单用户
				} else if (crowd == 2) {
					List<User> userList = userService.list(Wrappers.<User>lambdaQuery().in(User::getMerId, merIds));
					if (!CollectionUtils.isEmpty(userList)) {
						Iterator<User> iterator = userList.iterator();
						while (iterator.hasNext()) {
							User user = iterator.next();
							int orderCount = storeOrderService
									.count(Wrappers.<StoreOrder>lambdaQuery().eq(StoreOrder::getUid, user.getUid()));
							// 下过单的用户移除
							if (0 < orderCount) {
								iterator.remove();
							}
						}
					}
					users = userList;
				// 自定义人群
				} else if (crowd == 5) {
					// 分群id
					List<Integer> featureIds = storeCoupons.stream().map(StoreCoupon::getFeatureId).distinct().collect(Collectors.toList());
					// 查询用户分群下有哪些用户
					QueryWrapper<User> queryWrapper = new QueryWrapper<>();
					queryWrapper.apply(CrmebUtil.getFindInSetSql("feature_id", (ArrayList<Integer>) featureIds));
					queryWrapper.groupBy("uid");
					queryWrapper.lambda().in(User::getMerId, merIds);
					users = userService.list(queryWrapper);
				// 指定手机号用户
				} else if (crowd == 6) {
					// 优惠券id
					List<Integer> ids = storeCoupons.stream().map(StoreCoupon::getId).collect(Collectors.toList());
					List<StoreCouponUserPhone> storeCouponUserPhones = storeCouponUserPhoneService.list(Wrappers.<StoreCouponUserPhone>lambdaQuery()
							.in(StoreCouponUserPhone::getCouponId, ids)
							.eq(StoreCouponUserPhone::getStatus, true));
					if (!CollectionUtils.isEmpty(storeCouponUserPhones)) {
						List<String> phones = storeCouponUserPhones.stream().map(StoreCouponUserPhone::getPhone).distinct().collect(Collectors.toList());
						// 指定的手机号列表
						QueryWrapper<User> queryWrapper = new QueryWrapper<>();
						queryWrapper.in("SUBSTR(phone ,5)", phones);
						queryWrapper.lambda().in(User::getMerId, merIds);
						users = userService.list(queryWrapper);
					}
				}
				if (CollectionUtils.isEmpty(users)) {
					continue;
				}
				List<StoreCouponUser> storeCouponUsers = new ArrayList<>();
				List<User> finalUsers = users;
				storeCoupons.forEach(storeCoupon -> finalUsers.forEach(user -> {
					// 该用户领取过，将不发放
					if (receivedList.stream().anyMatch(storeCouponUser -> Objects.equals(storeCouponUser.getUid(), user.getUid()) && Objects.equals(storeCouponUser.getCouponId(), storeCoupon.getId()))) {
						return;
					}
					// 该用户所属商户下的优惠券进行发放
					if (Objects.equals(storeCoupon.getMerId(), user.getMerId())) {
						StoreCouponUser storeCouponUser = new StoreCouponUser();
						storeCouponUser.setMerId(storeCoupon.getMerId());
						storeCouponUser.setCouponId(storeCoupon.getId());
						storeCouponUser.setUid(user.getUid());
						storeCouponUser.setUserNick(user.getNickname());
						storeCouponUser.setUserPhone(user.getPhone());
						storeCouponUser.setName(storeCoupon.getName());
						storeCouponUser.setMoney(storeCoupon.getMoney());
						storeCouponUser.setUseType(storeCoupon.getUseType());
						storeCouponUser.setPrimaryKey(storeCoupon.getPrimaryKey());
						storeCouponUser.setMinPrice(storeCoupon.getMinPrice());
						storeCouponUser.setType(CouponUserTypeEnum.AUTO.getCode());
						storeCouponUser.setStatus(0);
						storeCouponUser.setCreateTime(new Date());
						// 固定时间
						if (storeCoupon.getIsFixedTime()) {
							storeCouponUser.setStartTime(storeCoupon.getUseStartTime());
							storeCouponUser.setEndTime(storeCoupon.getUseEndTime());
						// 有效天数
						} else {
							LocalDateTime time = LocalDateTime.now();
							LocalDateTime startTime = time.plusDays(storeCoupon.getLastDay());
							LocalDateTime endTime = startTime.plusDays(storeCoupon.getDay());

							ZoneId zoneId = ZoneId.systemDefault();
							Date startDate = Date.from(startTime.atZone(zoneId).toInstant());
							Date endDate = Date.from(endTime.atZone(zoneId).toInstant());

							storeCouponUser.setStartTime(startDate);
							storeCouponUser.setEndTime(endDate);
						}
						storeCouponUsers.add(storeCouponUser);
					}
				}));
				storeCouponUserService.saveBatch(storeCouponUsers);
			}
		}
	}

	private String getLock(String obj) {
		StringBuilder sb = new StringBuilder(obj);
		String lock = sb.toString().intern();

		return lock;
	}

	private List<StoreCoupon> getListByCrowd(Integer crowd) {
		// crowd类型 按月/周发放优惠券列表
		return this.list(Wrappers.<StoreCoupon>lambdaQuery()
				.eq(StoreCoupon::getType, 3)
				.eq(StoreCoupon::getCrowd, crowd)
				.eq(StoreCoupon::getIsDel, false)
				.eq(StoreCoupon::getStatus, false)
				.and(qr -> qr.eq(StoreCoupon::getReleaseType, 2)
						.eq(StoreCoupon::getReleaseDate, DateUtil.dayOfMonth(new Date()))
						.or()
						.eq(StoreCoupon::getReleaseType, 3)
						.eq(StoreCoupon::getReleaseDate, WeekEnum.getWeekDayByCode(String.valueOf(LocalDate.now().getDayOfWeek())))));
	}

}
